﻿namespace Arms.Application.Modules.Security
{
    using Arms.Application.Services;
    using Arms.Domain;
    using Arms.Domain.Modules.People;
    using Arms.Framework.Security;
    using Arms.Framework.Security.Encryptors;
    using System.Linq;

    /// <summary>
    /// Service that handles user authentication and data.
    /// </summary>
    public class MembershipService : ServiceBase, IMembershipService
    {
        public MembershipService(IUnitOfWork uow) : base(uow) { }

        /// <summary>
        /// Retrieve ArmsUserData by resolving the user
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public ArmsUserData GetArmsUserData(MembershipAuthenticationResult result)
        {
            if (result.IsAuthenticated)
            {
                var user = base.UnitOfWork.Repository<User>().Find(result.UserID);

                if (user != null)
                {
                    return new ArmsUserData()
                    {
                        UserID = user.ID,
                        UserClassID = user.UserClassID,
                        UserName = user.UserName,
                        EmailAddress = user.EmailAddress,
                        FirstName = user.FirstName,
                        LastName = user.LastName,
                        Roles = user.UserClass.Roles.Select(x => new ListItemDTO() { ItemID = x.ID, ItemName = x.Name }),
                        AppData = new AppData() { CurrentMenuID = user.AppConfig.CurrentMenuID, CurrentDiningRoomLayoutID = user.AppConfig.CurrentDiningRoomLayoutID }
                    };
                }
            }

            return null;
        }
        /// <summary>
        /// Determines whether username + password matches database.
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public MembershipAuthenticationResult Authenticate(string userName, string password)
        {
            MembershipAuthenticationResult result = new MembershipAuthenticationResult();

            var user = base.UnitOfWork.Repository<User>().Single(x => x.UserName == userName);

            if (user != null)
            {
                if (EncryptorFactory.Encryptor.IsMatch(user.Password, password + user.PasswordSalt))
                {
                    result.UserID = user.ID;
                    result.UserName = user.UserName;
                }
                else
                {
                    result.ErrorMessage = "Password incorrect";
                }
            }
            else
            {
                result.ErrorMessage = "Username incorrect";
            }

            return result;
        }
        /// <summary>
        /// Determines whether employee number matches database.
        /// </summary>
        /// <param name="employeeNumber"></param>
        /// <returns></returns>
        public MembershipAuthenticationResult Authenticate(long employeeNumber)
        {
            MembershipAuthenticationResult result = new MembershipAuthenticationResult();
            var employee = base.UnitOfWork.Repository<Employee>().Single(x => x.EmployeeNumber == employeeNumber);

            if (employee != null)
            {
                if (employee.Person != null)
                {
                    result.UserID = employee.Person.User.ID;
                    result.UserName = employee.Person.User.UserName;
                }
                else
                {
                    result.ErrorMessage = "Employee does not have an account.";
                }
            }
            else
            {
                result.ErrorMessage = "Employee does not exist.";
            }

            return result;
        }
    }
}
